package com.hyts.dbmeta.handler;

import com.hyts.dbmeta.error.DataBaseMetaError;
import com.hyts.dbmeta.model.ColumnMetadata;
import com.hyts.dbmeta.model.DataSourceMetadata;
import com.hyts.dbmeta.model.TableMetadata;
import com.hyts.dbmeta.model.ViewMetadata;
import lombok.Builder;
import lombok.NoArgsConstructor;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * project-name:coffice-wizard
 * package-name:com.hyts.dbmeta.handler
 * author:Libo/Alex
 * create-date:2018-11-04 18:31
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于: 数据库元数据处理器句柄类
 */
@NoArgsConstructor
@Builder
public class DBMetadataHandler {


    /**
     * @param connection
     * @return
     * @throws SQLException
     */
    public DataSourceMetadata getDataSourceMetadata(Connection connection) throws SQLException {
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        DataSourceMetadata dataBaseMetaData = new DataSourceMetadata();
        //转换较为简单的基础类
        dataBaseMetaData.setDriverName(databaseMetaData.getDriverName());
        dataBaseMetaData.setDriverVersion(databaseMetaData.getDriverVersion());
        dataBaseMetaData.setName(databaseMetaData.getDatabaseProductName());
        dataBaseMetaData.setUserName(databaseMetaData.getUserName());
        dataBaseMetaData.setReadOnly(databaseMetaData.isReadOnly());
        dataBaseMetaData.setUrl(databaseMetaData.getURL());
        dataBaseMetaData.setVersion(databaseMetaData.getDatabaseProductVersion());
        return dataBaseMetaData;
    }

    /**
     * 获取
     * @return
     */
    public List<TableMetadata> getTableMetadata(Connection connection) throws SQLException {
        //获取结果集操作
        ResultSet tableList = getBaseMetadata(connection,new String[]{"TABLE"});
        List<TableMetadata> tableLists = new ArrayList<>();
        try {
            while(tableList.next()){
                TableMetadata tableMetadata = new TableMetadata(tableList.getString(1),tableList.getString(3),tableList.getString(4));
                tableMetadata.setColumnMetadataList(getColumnMetadata(connection,tableMetadata));
                tableLists.add(tableMetadata);
            }
        } catch (SQLException e) {
            throw new DataBaseMetaError("查询数据库元数据失败!",e);
        }
        return tableLists;
    }

    /**
     * 获取列标记操作
     * @return
     */
    public List<ColumnMetadata> getColumnMetadata(Connection connection,TableMetadata tableMetadata) throws SQLException {
        ResultSet rs = connection.getMetaData().getColumns(null,  connection.getMetaData().getUserName(),
                tableMetadata.getName(), "%");
        if(rs!=null){
            List<ColumnMetadata> columnMetadata = new LinkedList<>();
            while(rs.next()){
                columnMetadata.add(ColumnMetadata.builder().columnName(rs.getString("COLUMN_NAME"))
                        .jdbcType(rs.getString("TYPE_NAME"))
                        .remarks(rs.getString("REMARKS")).build());
            }
            return columnMetadata;
        }
        return new LinkedList<>();
    }

    /**
     * 获取视图元数据
     * @return
     */
    public List<ViewMetadata> getViewMetadata(Connection connection) throws SQLException {
        //获取结果集操作
        ResultSet viewList = getBaseMetadata(connection,new String[]{"VIEW"});
        List<ViewMetadata> tableLists = new ArrayList<>();
        while(viewList.next()){
            System.out.println(viewList.getString(1));
        }
        return tableLists;
    }

    /**
     * 获取基础元数据功能实现抽象
     * @return
     */
    private ResultSet getBaseMetadata(Connection connection,String... type) throws SQLException {
       return getBaseMetadata(connection,null,null,null,type);
    }

    /**
     * 获取基础元数据功能实现
     * @param connection
     * @param catalog
     * @param schemePattern
     * @param tableNamePattern
     * @param type
     * @return
     * @throws SQLException
     */
    private ResultSet getBaseMetadata(Connection connection,String catalog,String schemePattern,String tableNamePattern,String... type) throws SQLException {
        if(connection == null){
            throw new DataBaseMetaError("传入的Connection数据对象不可以为空!");
        }
        ResultSet objects = connection.getMetaData().getTables(catalog, schemePattern == null ? "%": schemePattern, tableNamePattern, type);
        return objects;
    }

}
